use axum::{
    Router,
    extract::{
        State,
        ws::{Message, WebSocket, WebSocketUpgrade},
    },
    response::IntoResponse,
    routing::{get, post},
};
use std::sync::Arc;

#[cfg(debug_assertions)]
use axum::response::Redirect;

// use chrono::Utc;
// use sha2::{Digest, Sha256};
use serde::{Deserialize, Serialize};
use tokio::sync::broadcast;

use bc_manager::BcManagerHandler;

use crate::handler::{
    create_account::create_account, mine_block::mine_block, query_balance::query_balance,
    query_transaction::query_transaction, send_transaction::send_transaction,
};

pub(crate) mod handler;

#[derive(Debug, Serialize, Deserialize, Clone)]
struct BlockId {
    id: String,
}

pub(crate) struct AppState {
    tx: broadcast::Sender<BlockId>,
    bc_manager: BcManagerHandler,
}
//
// https://docs.rs/axum/latest/axum/handler/index.html
// https://docs.rs/axum/latest/axum/extract/index.html
//
pub fn create_router(bc_manager: BcManagerHandler) -> Router {
    let (tx, _rx) = broadcast::channel(100);
    // let genesis_block = Block {
    //     index: 0,
    //     previous_hash: "0".to_string(),
    //     hash: "genesis_hash".to_string(),
    //     timestamp: Utc::now().timestamp() as u64,
    //     transactions: vec!["Genesis Block".to_string()],
    // };

    let app_state = Arc::new(AppState {
        // blocks: Arc::new(Mutex::new(vec![genesis_block])),
        tx,
        bc_manager,
    });

    // let index_html = std::fs::read_to_string("./bc/web_frontend/index.html")
    // .expect("Failed to read index.html");

    #[cfg(not(debug_assertions))]
    let app = Router::new()
        .fallback_service(tower_http::services::ServeDir::new(
            "bc_explorer/frontend/dist",
        )) // 提供前端静态文件（生产模式）
        .route("/ws", get(websocket_handler))
        .route("/api/account/create", post(create_account))
        .route("/api/transaction/send", post(send_transaction))
        .route("/api/transaction/{txid}", get(query_transaction))
        .route("/api/balance", post(query_balance))
        .route("/api/mine", post(mine_block))
        .with_state(app_state.clone());

    #[cfg(debug_assertions)]
    let app = Router::new()
        // .route("/", get({
        //     let index_html = index_html.clone();
        //     move || async { Html(index_html) }})) // 返回 index.html
        .route(
            "/",
            get(|| async { Redirect::temporary("http://127.0.0.1:5173/") }),
        )
        // .route("/blocks", get(get_blocks))
        .route("/ws", get(websocket_handler))
        .route("/api/account/create", post(create_account))
        .route("/api/transaction/send", post(send_transaction))
        .route("/api/transaction/{txid}", get(query_transaction))
        .route("/api/balance", post(query_balance))
        .route("/api/mine", post(mine_block))
        .with_state(app_state.clone());

    app
}

async fn websocket_handler(
    ws: WebSocketUpgrade,
    State(state): State<Arc<AppState>>,
) -> impl IntoResponse {
    ws.on_upgrade(move |socket| handle_socket(socket, state))
}

async fn handle_socket(mut socket: WebSocket, state: Arc<AppState>) {
    let mut rx = state.tx.subscribe();
    while let Ok(block) = rx.recv().await {
        let msg = serde_json::to_string(&block).unwrap();
        if socket.send(Message::Text(msg.into())).await.is_err() {
            break;
        }
    }
}
